//
// Copyright © 2025 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Package profile provides video profiles
package profile

import (
	"fmt"

	"github.com/hcengineering/stream/internal/pkg/resconv"
)

// VideoProfile represents a video profile
type VideoProfile struct {
	Name      string
	Width     int // 0 means keep original
	Height    int // 0 means keep original
	Bandwidth int
	Scale     bool

	// Codec settings
	VideoCodec string
	AudioCodec string

	// Advanced encoding settings
	CRF int // Constant Rate Factor (0-51 for x264)
}

// profileOriginal is a profile for original video without transcoding
var profileOriginal = VideoProfile{
	Name:       "orig",
	Scale:      false,
	VideoCodec: "copy",
	AudioCodec: "copy",
	CRF:        23,
}

// profileOriginalT is a profile for transcoding video in the original resolution
var profileOriginalT = VideoProfile{
	Name:       "orig",
	Scale:      false,
	VideoCodec: "libx264",
	AudioCodec: "aac",
	CRF:        23,
}

// Profile360p is a profile for transcoding video in 360p
var Profile360p = VideoProfile{
	Name:       "360p",
	Scale:      true,
	Width:      640,
	Height:     360,
	Bandwidth:  500000,
	VideoCodec: "libx264",
	AudioCodec: "aac",
	CRF:        28,
}

// Profile480p is a profile for transcoding video in 480p
var Profile480p = VideoProfile{
	Name:       "480p",
	Scale:      true,
	Width:      854,
	Height:     480,
	Bandwidth:  2000000,
	VideoCodec: "libx264",
	AudioCodec: "aac",
	CRF:        27,
}

// Profile720p is a profile for transcoding video in 720p
var Profile720p = VideoProfile{
	Name:       "720p",
	Scale:      true,
	Width:      1280,
	Height:     720,
	Bandwidth:  5000000,
	VideoCodec: "libx264",
	AudioCodec: "aac",
	CRF:        25,
}

// Profile1080p is a profile for transcoding video in 1080p
var Profile1080p = VideoProfile{
	Name:       "1080p",
	Scale:      true,
	Width:      1920,
	Height:     1080,
	Bandwidth:  8000000,
	VideoCodec: "libx264",
	AudioCodec: "aac",
	CRF:        23,
}

// Profile1440p is a profile for transcoding video in 1440p
var Profile1440p = VideoProfile{
	Name:       "1440p",
	Scale:      true,
	Width:      2560,
	Height:     1440,
	Bandwidth:  12000000,
	VideoCodec: "libx264",
	AudioCodec: "aac",
	CRF:        23,
}

// Profile2160p is a profile for transcoding video in 2160p
var Profile2160p = VideoProfile{
	Name:       "2160p",
	Scale:      true,
	Width:      3840,
	Height:     2160,
	Bandwidth:  25000000,
	VideoCodec: "libx264", // Consider libx265
	AudioCodec: "aac",
	CRF:        22,
}

// Profile4320p is a profile for transcoding video in 360p
var Profile4320p = VideoProfile{
	Name:       "4320p",
	Scale:      true,
	Width:      7680,
	Height:     4320,
	Bandwidth:  50000000,
	VideoCodec: "libx264", // Consider libx265
	AudioCodec: "aac",
	CRF:        22,
}

// Profiles is a map of all supported profiles
var Profiles = map[string]VideoProfile{
	"360p":  Profile360p,
	"480p":  Profile480p,
	"720p":  Profile720p,
	"1080p": Profile1080p,
	"1440p": Profile1440p,
	"2160p": Profile2160p,
	"4320p": Profile4320p,
}

// MakeProfileOriginal creates a profile for original video without transcoding
func MakeProfileOriginal(width, height int) VideoProfile {
	resolution := fmt.Sprintf("%v:%v", width, height)
	level := resconv.Level(resolution)
	bandwidth := resconv.Bandwidth(level)

	profile := profileOriginal
	profile.Width = width
	profile.Height = height
	profile.Bandwidth = bandwidth

	return profile
}

// MakeProfileOriginalT creates a profile for transcoding video in the original resolution
func MakeProfileOriginalT(width, height int) VideoProfile {
	resolution := fmt.Sprintf("%v:%v", width, height)
	level := resconv.Level(resolution)
	bandwidth := resconv.Bandwidth(level)

	profile := profileOriginalT
	profile.Width = width
	profile.Height = height
	profile.Bandwidth = bandwidth

	return profile
}

// GetProfileByName returns a VideoProfile by name
func GetProfileByName(name string) (VideoProfile, bool) {
	profile, ok := Profiles[name]
	return profile, ok
}
